<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script src="./d3.js"></script>
<script>

    const svg = d3.select('body').append('svg').attr('width', 1600).attr('height', 800).attr('id', "mainsvg").attr('class', "svgs")
    const width = svg.attr("width")
    const height = svg.attr("height")
    // const margin = {top: 60, right: 60, bottom: 60, left: 50};
    const margin = {top: 60, right: 60, bottom: 100, left: 120};

    const innerWidth = width - margin.left - margin.right;
    const innerHeight = height - margin.top - margin.bottom;
    var color = {
        "武汉": "#ff1c12",
        "黄石": "#de5991",
        "十堰": "#759AA0",
        "荆州": "#E69D87",
        "宜昌": "#be3259",
        "襄阳": "#EA7E53",
        "鄂州": "#EEDD78",
        "荆门": "#9359b1",
        "孝感": "#47c0d4",
        "黄冈": "#F49F42",
        "咸宁": "#AA312C",
        "恩施州": "#B35E45",
        "随州": "#4B8E6F",
        "仙桃": "#ff8603",
        "天门": "#ffde1d",
        "潜江": "#1e9d95",
        "神农架": "#7289AB"
    }
    const xAxisLabel = '累计确诊人数（对数）';
    const yAxisLabel = '新增人数（对数）';
    let xScale, yScale;
    let xValue = d => Math.log(d['确诊人数'] + 1);
    let yValue = d => Math.log(d['新增确诊'] + 1);
    const rValue = d => {return Math.sqrt(d['感染率'] * 500) * 0.8;};
    let intervalId;
    let aduration = 1000
    const renderinit = (data) => {
        xScale = d3.scaleLinear()
            .domain(d3.extent(data, xValue))//设置数据规则// "extent" is equivalent to [d3.min, d3.max]
            .range([0, innerWidth])//设置起始与终止点坐标
            .nice()
        yScale = d3.scaleLinear()
            .domain(d3.extent(data, yValue).reverse())// 因为d3坐标轴从上往下   所以在y坐标为规律时需要反转一下
            .range([0, innerHeight])
            .nice()
        const g = svg.append('g').attr('transform', `translate(${margin.left}, ${margin.top})`).attr("id", "maingroup")

        const yAxis = d3.axisLeft(yScale)
            .tickSize(-innerWidth)
            //.tickFormat(d3.format('.2s'))
            .tickPadding(10); // .tickPadding is used to prevend intersection of ticks; 
        const xAxis = d3.axisBottom(xScale)
            //.tickFormat(d3.format('.2s'))
            .tickSize(-innerHeight)
            .tickPadding(10);

        let yAxisGroup = g.append('g').call(yAxis)
            .attr('id', 'yaxis');
        yAxisGroup.append('text')
            .attr('font-size', '1.5em')
            .attr('transform', `rotate(-90)`)
            .attr('x', -innerHeight / 2)
            .attr('y', -40)
            .attr('fill', '#333333')
            .text(yAxisLabel)
            .attr('text-anchor', 'middle') // Make label at the middle of axis. 
        yAxisGroup.selectAll('.domain').remove(); // we can select multiple tags using comma to seperate them and we can use space to signify nesting; 

        let xAxisGroup = g.append('g').call(xAxis)
            .attr('transform', `translate(${0}, ${innerHeight})`)
            .attr('id', 'xaxis');
        xAxisGroup.append('text')
            .attr('font-size', '1.5em')
            .attr('y', 40)
            .attr('x', innerWidth / 2)
            .attr('fill', '#333333')
            .text(xAxisLabel);
        xAxisGroup.selectAll('.domain').remove();
    }
    let alldates = []
    let sequantial = []
    let time

    const renderUpdate = (seq) => {
        const g = d3.select('#maingroup')

        time = seq[0]['日期'];
        g.selectAll('.date_text').remove();
        g.append("text")
            .data(['seq'])
            .attr('class', 'date_text')
            .attr("x", innerWidth / 4 + 30)
            .attr("y", innerHeight / 10 - 20)
            .attr("dy", ".5em")
            .style("text-anchor", "end")
            .attr("fill", "#504f4f")
            .text(time)
            .attr("font-size", '6em')

        let circleText = g.selectAll(".circleText").data(seq, (d) => {
            return d["地区"]
        })
        let textEnter = circleText.enter().append('text')
            .attr('x', (datum) => {return xScale(xValue(datum));})
            .attr('y', (datum) => {return yScale(yValue(datum));})
            .attr("class", "circleText")
            .style("text-anchor", "middle")
            .attr('fill', '#000000')
            .text(d => d["地区"])
            .attr('font-size', '1em')
            .attr("dy", "1em")//平移  dy  sx


        let circleupdates = g.selectAll("circle").data(seq, d => d["地区"])
        let circleEnter = circleupdates.enter().append('circle')
            .attr('cx', d => xScale(xValue(d)))
            .attr('cy', d => yScale(yValue(d)))
            .attr('r', d => rValue(d))
            .attr('fill', d => color[d["地区"]])
            .attr('opacity', 0.8)
        // ease(d3.easeLinear)线性更新
        circleupdates.merge(circleEnter).transition().ease(d3.easeLinear).duration(aduration)
            .attr('cx', d => xScale(xValue(d)))
            .attr('cy', d => yScale(yValue(d)))
            .attr('r', d => rValue(d))
        textEnter.merge(circleText).transition().ease(d3.easeLinear).duration(aduration)
            .attr('x', d => xScale(xValue(d)))
            .attr('y', d => yScale(yValue(d)))
        // .attr('r', d => d["确诊人数"])

    }
    let metapop = []
    d3.csv('./static/data/hubeipop.csv').then(data => {
        data.forEach(datum => {
            datum['人口（万人）'] = +(datum['人口（万人）']);
        })
        metapop = data;
    });
    d3.csv("./static/data/hubei_day14.csv").then(res => {
        const data = res.filter(d => {
            return d["地区"] !== "总计"
        }).map(item => {
            let before = {...item}
            Object.keys(before).forEach(key => {
                if (key !== "地区" && key !== "日期") {
                    before[key] = parseInt(before[key])
                    if (before[key] < 0) {
                        before[key] = 0
                    }
                    before['感染率'] = before['确诊人数'] / (metapop.find(x => x["地区"] === before["地区"])['人口（万人）']);
                }
            })

            return before
        })
        alldates = Array.from(new Set(data.map(item => item["日期"]))).sort((a, b) => {
            return new Date(a) - new Date(b)
        })
        alldates.forEach(item => {
            sequantial.push([])
        })
        data.forEach((d) => {
            sequantial[alldates.indexOf(d["日期"])].push(d)
        })
        renderinit(data)
        let c = 0;
        intervalId = setInterval(() => {
            if (c >= alldates.length) {
                clearInterval(intervalId);
            } else {
                renderUpdate(sequantial[c])
                c += 1
            }
        }, aduration)
        // console.log(alldates);
        console.log(sequantial);
    })
</script>

</html>
